home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / mail / mh / vmail / vmail.1of3 < prev    next >
Text File  |  1991-04-05  |  55KB  |  2,099 lines

  1. (Message mh:6)
  2. Resent: Mon, 25 Mar 91 10:18:38 PST
  3. Resent: qq11@uxb.liv.ac.uk (Alan Thew)
  4. Resent: Mon, 18 Mar 91 12:21:43 PST
  5. Resent: jcohn@nsf.gov (Johnathan Charles Cohn)
  6. Resent: rjg@sq.com (Bob Gibson)
  7. Resent: dak@sq.com (David Keldson)
  8. Resent: sow@cad.luth.se (Sven-Ove Westberg)
  9. Resent: cenkl@linus.mitre.org (Mike Cenkl)
  10. Resent: david@scocan.sco.com (David J Fiander)
  11. Return-Path: jamesp@metolius.WR
  12. To: luj@ecn.purdue.edu (Jun Lu), jkm@ctt.bellcore.COM (James Mcglashan),
  13.         jmvogtle@gamera.cns.syr.edu (John M Vogtle),
  14.         cks@hawkwind.utcs.toronto.edu (Chris Siebenmann),
  15.         ccw@deakin.OZ.AU (Craig Warren), rr@mips.COM (Robert "Bob" Rodriguez),
  16.         munck@Stars.Reston.Unisys.COM (Bob Munck)
  17. Cc: jamesp@metolius.WR.TEK.COM (James Perkins)
  18. Subject: Vmail - version 10/87DAS
  19. Reply-To: jamesp@metolius.WR.TEK.COM (James T. Perkins)
  20. X-Mailer: Rand MH 6.6 - Vmail 10/87DAS - Vmailtool V1.14 91/02/27
  21. Date: Mon, 11 Mar 91 11:37:16 PST
  22. From: James T Perkins <jamesp@metolius.WR>
  23. --------
  24.  
  25.  
  26. Okay, folks, you asked for it.  Here it is: the Tektronix Logic
  27. Analyzers DAS Engineering local hack to Vmail, the user-friendly,
  28. curses-based, MH-calling mail program.  It is useless unless you have MH
  29. installed and available in your PATH.  It works with MH version 5.1 or
  30. better.
  31.  
  32. There is a SunView button panel available for vmail, called vmailtool,
  33. available from me.  This helps users who can't remember which keys to
  34. press on vmail, instead having a layer of menus, buttons, and dialog
  35. boxes atop vmail.  It is written in tooltool, a quick gadget panel
  36. specification language.  Tooltool applications run under both sunview
  37. and openwindows, but not X11/motif or X11/uwm and their ilk.
  38.  
  39.  ___    ___   ___
  40. |   \  / _ \ / __|  James Perkins, jamesp@metolius.wr.tek.com, (503)629-1149
  41. | |> || |_| |\__ \  Logic Analyzers Division, DAS 9200 Engineering
  42. |___/ |_| |_||___/  Tektronix, MS 92-725, PO Box 4600, Beaverton, OR 97076
  43.  
  44. This package is sold by weight, not by volume.  Some settling of contents may
  45. have occurred during shipping and handling.
  46.  
  47. #! /bin/sh
  48. # This is a shell archive.  Remove anything before this line, then unpack
  49. # it by saving it into a file and typing "sh file".  To overwrite existing
  50. # files, type "sh file -c".  You can also feed this as standard input via
  51. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  52. # will see the following message at the end:
  53. #        "End of archive 1 (of 3)."
  54. # Contents:  CHANGES MANIFEST Makefile READ_ME choose.c cmds.c defs.h
  55. #   find.c inc.c low.c macro.h page.c refresh.c
  56. # Wrapped by jamesp@metolius on Mon Mar 11 11:20:04 1991
  57. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  58. if test -f CHANGES -a "${1}" != "-c" ; then 
  59.   echo shar: Will not over-write existing file \"CHANGES\"
  60. else
  61. echo shar: Extracting \"CHANGES\" \(2828 characters\)
  62. sed "s/^X//" >CHANGES <<'END_OF_CHANGES'
  63. X
  64. X                      Modifications Summary
  65. X
  66. X                          March 8, 1991
  67. X
  68. X                          James Perkins
  69. X                   jamesp@metolius.wr.tek.com
  70. X
  71. XThis is a summary of James Perkins' modifications to J.  Zobel's 1987
  72. Xvmail distribution.
  73. X
  74. XMakefile
  75. X    added targets: install, Saber, lint, tags, source, shar, depend.
  76. X    added STANDOUT_CLEANUP define.
  77. X
  78. Xvmail.1
  79. X    Added new commands, bugs, and history section.
  80. X
  81. Xdefs.h
  82. X    added "sig_type" type (SunOS Port)
  83. X    added includes of appropriate std includes.
  84. X    lint cleanup - cast to void everywhere.
  85. X    added memalign() extern for Sparc
  86. X    COMP, FORW, INC, REPL, PAGER, EDITOR, SHELL now relative pathnames.
  87. X    Added BURST, DIST, SORTM defines.
  88. X    Added CRTL_R define.
  89. X    Added externs for new functions.
  90. X
  91. Xmacro.h
  92. X    lint cleanup - cast to void everywhere.
  93. X    use of memalign() instead of malloc() for Sparc.
  94. X
  95. Xcall.c
  96. X    signal commands now of type "sig_type" (SunOS Port)
  97. X    lint cleanup - cast to void everywhere.
  98. X    execv changed to execvp so user can have personal versions of comp, etc.
  99. X    addstatus warning added where necessary.
  100. X    added burst_item(), dist_item(), sort_folder() function.
  101. X
  102. Xchoose.c
  103. X    lint cleanup - cast to void everywhere.
  104. X
  105. Xcmds.c
  106. X    signal commands now of type "sig_type" (SunOS Port)
  107. X    lint cleanup - cast to void everywhere.
  108. X
  109. Xfind.c
  110. X    lint cleanup - cast to void everywhere.
  111. X
  112. Xinc.c
  113. X    lint cleanup - cast to void everywhere.
  114. X    execl changed to execlp so user can have personal versions of inc, etc.
  115. X
  116. Xinit.c
  117. X    lint cleanup - cast to void everywhere.
  118. X    signal commands now of type "sig_type" (SunOS Port)
  119. X    added tstp(), tint() externs.
  120. X    added stdout_cleanup, which causes stdout to always be turned off
  121. X        when a child is spawned and waited for.  It's a yucky kludge
  122. X        but necessary.
  123. X
  124. Xload.c
  125. X    now symlinks to mail folders are permitted, and reallocs are done right.
  126. X    use of memalign() instead of malloc() for Sparc.
  127. X    lint cleanup - cast to void everywhere.
  128. X    file name space compression now done more intelligently.
  129. X
  130. Xlow.c
  131. X    putchar now returns status.
  132. X    lint cleanup - cast to void everywhere.
  133. X
  134. Xmain.c
  135. X    lint cleanup - cast to void everywhere.
  136. X    sets and recognizes options for -burst, -dist, -sort
  137. X    added new commands to help text.
  138. X    help text length macro now dynamically sized.
  139. X    added new commands 'b', 't', 'S', '^R'  to command switch.
  140. X    cast wait argument to type (union wait *)
  141. X
  142. Xmove.c
  143. X    lint cleanup - cast to void everywhere.
  144. X    Now removal of only item on last page of folder will send you to
  145. X        the last item on previous page of the folder, if possible.
  146. X
  147. Xpage.c
  148. X    lint cleanup - cast to void everywhere.
  149. X    fix bug due to walking off end of folder list when looking for the
  150. X        next/prev folder.
  151. X
  152. Xrefresh_folder.c
  153. X    Added new source module, which takes an existing folder and
  154. X        rescans the source listing.  Needed for "^R" resync,
  155. X        'b' burst, and 'S' sortm commands.
  156. X
  157. XEND OF SUMMARY
  158. END_OF_CHANGES
  159. if test 2828 -ne `wc -c <CHANGES`; then
  160.     echo shar: \"CHANGES\" unpacked with wrong size!
  161. fi
  162. # end of overwriting check
  163. fi
  164. if test -f MANIFEST -a "${1}" != "-c" ; then 
  165.   echo shar: Will not over-write existing file \"MANIFEST\"
  166. else
  167. echo shar: Extracting \"MANIFEST\" \(684 characters\)
  168. sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
  169. X   File Name        Archive #    Description
  170. X-----------------------------------------------------------
  171. X CHANGES                   1    
  172. X MANIFEST                  1    This shipping list
  173. X Makefile                  1    
  174. X READ_ME                   1    
  175. X call.c                    2    
  176. X choose.c                  1    
  177. X cmds.c                    1    
  178. X defs.h                    1    
  179. X find.c                    1    
  180. X inc.c                     1    
  181. X init.c                    2    
  182. X load.c                    3    
  183. X low.c                     1    
  184. X macro.h                   1    
  185. X main.c                    2    
  186. X move.c                    2    
  187. X page.c                    1    
  188. X refresh.c                 1    
  189. X vmail.1                   2    
  190. END_OF_MANIFEST
  191. if test 684 -ne `wc -c <MANIFEST`; then
  192.     echo shar: \"MANIFEST\" unpacked with wrong size!
  193. fi
  194. # end of overwriting check
  195. fi
  196. if test -f Makefile -a "${1}" != "-c" ; then 
  197.   echo shar: Will not over-write existing file \"Makefile\"
  198. else
  199. echo shar: Extracting \"Makefile\" \(1936 characters\)
  200. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  201. X#    vmail
  202. X#
  203. X#    Interactive screen-based mail handler that sits on top of MH.
  204. X#
  205. X#    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  206. X#
  207. X# $Id: Makefile,v 1.13 91/03/11 11:19:26 jamesp Exp $
  208. X#
  209. X
  210. XDESTDIR = /usr/local
  211. XMANDIR = /usr/manl/man1
  212. XOWNER = bin
  213. XGROUP = lclsrc
  214. X
  215. XCFILES = call.c choose.c cmds.c find.c inc.c init.c load.c low.c main.c \
  216. X    move.c page.c refresh.c
  217. X
  218. XINCLUDES = defs.h macro.h 
  219. X
  220. XSHARFILES = READ_ME CHANGES vmail.1 Makefile $(CFILES) $(INCLUDES)
  221. X
  222. XOBJS = call.o choose.o cmds.o find.o inc.o init.o load.o low.o main.o \
  223. X    move.o page.o refresh.o
  224. X
  225. XVERS=\"10/87DAS\"
  226. X
  227. X#
  228. X# Define USDATE for U.S. date format on scan
  229. X#
  230. X
  231. XDEFINES = -DVERSION=$(VERS) -DUSDATE -DSTANDOUT_CLEANUP
  232. X
  233. XCFLAGS = -O $(DEFINES)
  234. X
  235. XLDFLAGS = -s
  236. X
  237. XLINT = lint
  238. XLFLAGS = $(DEFINES)
  239. X
  240. XLIBS = -lcurses -ltermcap
  241. X
  242. Xvmail: $(OBJS)
  243. X    $(CC) $(LDFLAGS) -o vmail $(OBJS) $(LIBS)
  244. XSaber:
  245. X    #load $(CFLAGS) $(CFILES) $(HFILES) $(LIBS) -lc
  246. X
  247. Xlint:
  248. X    $(LINT) $(LFLAGS) $(CFILES) $(LIBS)
  249. X
  250. Xinstall : $(DESTDIR)/vmail $(MANDIR)/vmail.1
  251. X
  252. X$(DESTDIR)/vmail: vmail
  253. X    install -c -o $(OWNER) -g $(GROUP) -m 0751 vmail $(DESTDIR)
  254. X
  255. X$(MANDIR)/vmail.1 : vmail.1
  256. X    install -C -c -o $(OWNER) -g $(GROUP) -m 0644 vmail.1 $(MANDIR)
  257. X
  258. Xclean:
  259. X    rm -f *.[cho1] core vmail make.out tags
  260. X
  261. Xtags: source
  262. X    ctags -w $(CFILES) $(INCLUDES)
  263. X
  264. Xvmail.1 READ_ME CHANGES Makefile:
  265. X    $(CO) $(COFLAGS) $@
  266. X
  267. Xvmail.man: vmail.1
  268. X    nroff -man $? > $@
  269. X
  270. Xsource: $(CFILES) $(INCLUDES)
  271. X
  272. Xmakekit: $(SHARFILES)
  273. X    makekit -m $(SHARFILES)
  274. X
  275. Xdepend : source
  276. X    maketd $(DEFINES) $(CFILES)
  277. X
  278. X# DO NOT DELETE THIS LINE - make maketd DEPENDS ON IT
  279. X# Dependencies generated at: Thu Oct 15 13:21:02 PDT 1987
  280. X
  281. Xcall.o:    defs.h  macro.h  
  282. Xchoose.o:    defs.h  macro.h  
  283. Xcmds.o:    defs.h  macro.h  
  284. Xfind.o:    defs.h  macro.h  
  285. Xinc.o:    defs.h  macro.h  
  286. Xinit.o:    defs.h  macro.h  
  287. Xload.o:    defs.h  macro.h  
  288. Xlow.o:    defs.h  macro.h  
  289. Xmain.o:    defs.h  macro.h  
  290. Xmove.o:    defs.h  macro.h  
  291. Xpage.o:    defs.h  macro.h  
  292. X
  293. X# DO NOT ADD ANYTHING HERE - WILL GO AWAY
  294. END_OF_Makefile
  295. if test 1936 -ne `wc -c <Makefile`; then
  296.     echo shar: \"Makefile\" unpacked with wrong size!
  297. fi
  298. # end of overwriting check
  299. fi
  300. if test -f READ_ME -a "${1}" != "-c" ; then 
  301.   echo shar: Will not over-write existing file \"READ_ME\"
  302. else
  303. echo shar: Extracting \"READ_ME\" \(4838 characters\)
  304. sed "s/^X//" >READ_ME <<'END_OF_READ_ME'
  305. X$Header: /mnts/metolius/home/jamesp/usr/src/vmail/RCS/READ_ME,v 1.1 87/10/15 13:40:18 rogers Exp $
  306. X
  307. XVMAIL is copyright (C) J. Zobel, University of Melbourne, October 1987.
  308. XPermission to copy and modify vmail is given in full, but copies and
  309. Xmodified copies must contain this copyright notice.
  310. X
  311. X    vmail is an interactive mail handler that sits on top of MH6.5.
  312. XBecause vmail updates the MH environment by updating .mh_sequences,
  313. Xit is not compatible with early versions of MH, although it should
  314. Xwork with MH5 and possibly MH4.
  315. X
  316. X    vmail has a number of advantages over raw MH.  It is screen-based and
  317. Xfaster (and more convenient) than the MH show-scan-rmm refile cycle.
  318. XThe `scan' pages for the specified folders are loaded at start up time;
  319. Xfurther folders may be loaded at any time.  `scan' is replaced by paging
  320. Xbetween screens of stored information, `show' by a fork() to a pager,
  321. X`rmm' and `refile' by calls to rename (2).  Other features, such as folder
  322. Xpacking, are also faster, as most of the required information is already
  323. Xknown to the process.  vmail makes it feasible for users to organise and
  324. Xkeep track of moderate volumes of mail without wasting too much time, and
  325. Xis very simple to use.  It has been in use at Melbourne University Computer
  326. XScience Department for about six months without any problems, and has
  327. Xbecome the interface of choice for many users.  Users who (being new to
  328. XUNIX) were introduced to mail with vmail have never tried the MH commands
  329. Xthemselves, being satisfied with the vmail interface and wanting to avoid
  330. Xthe plethora of MH functions and usages.
  331. X
  332. X
  333. XTechnical Notes
  334. X
  335. X    vmail is currently Berkeley specific, in particular use of signal(),
  336. Xvfork(), ioctl() and union wait.  It should work with most versions of MH,
  337. Xbut makes assumptions about the structure of folders, ie, that a folder is
  338. Xa directory containing files whose names are numbers (other files are
  339. Xignored).  By default, a .mh_profile is required to specify alternatives
  340. Xto other defaults such as name of mail directory; the environment variable
  341. XMH may be used to set an alternative profile.  The usual assumptions are
  342. Xmade about the format of mail items - use of fields (if present) such as
  343. X"To:", "From:" and so on, but these also should not cause any difficulties.
  344. X    comp, repl and forw are all forked from vmail rather than imitated,
  345. Xthere being no real time advantage to doing otherwise, but are given by
  346. Xsingle-letter commands rather than longer commands to a shell.  Most MH
  347. Xoptions as set in the profile are ignored (most are not relevant);
  348. Xbecause comp, repl, etc are forks rather than built-ins, this is not
  349. Xreally a problem.  The paths for these executables are in defs.h and
  350. Xmay have to be changed.
  351. X    The most unreliable feature is probably the parsing of inc output in
  352. Xinc.c, used when `i' is given to incorporate new mail.  Because some people
  353. Xlike to give options to inc in their profile, and because inc was too long
  354. Xto consider rewriting, the simplest solution was to parse the inc output -
  355. Xif the format changed this code would break.
  356. X    Some may find the mixture of stdio, curses and ioctl ugly, but it is
  357. Xreasonably orthogonal - stdio is used when tty is in normal mode, curses
  358. Xwhen control is required, and ioctl and signal when processes are being
  359. Xsuspended, woken or forked.
  360. X
  361. XMade with "make" (no arguments).  If cc does not recognize -k option,
  362. Xvalue of make variable STACK must be changed.  The compiler option
  363. X-DUSDATE must be set if dates are to be displayed in US format.
  364. X
  365. XFiles
  366. X
  367. X    READ_ME            This file.
  368. X    vmail.1            Manual entry.
  369. X    Makefile        Version number.
  370. X
  371. X    defs.h            Pathnames, defaults, structs, externs,
  372. X                constants.  Some of these will need to be
  373. X                edited, eg locations of MH routines.
  374. X    macro.h            Simple functions.
  375. X
  376. X    call.c            Forks to MH functions, editor, shell.
  377. X    choose.c        Folder chooser, folder display.
  378. X    cmds.c            Assorted commands.
  379. X    find.c            Searching through headers for strings.
  380. X    inc.c            Handles fork to inc, parsing of inc output.
  381. X    init.c            Startup, interrupt handling.
  382. X    load.c            Loading of folders/mail from mail directory
  383. X                into internal structures.
  384. X    low.c            Some primitive functions.
  385. X    main.c            High-level switch.
  386. X    move.c            Commands for refile, delete, undo.
  387. X    page.c            Commands associated with movement between
  388. X                pages and movement within a page.
  389. X
  390. XNB: All source files are formatted with tabstop=4.
  391. X
  392. X===============================================================================
  393. X
  394. XI would appreciate hearing about bugs/bug fixes/amendments/improvements/
  395. Xadditions; any correspondence should be sent to
  396. X
  397. XUUCP:    ...!munnari!mulga!jz
  398. XARPA:    jz%mulga.oz@uunet.uu.net
  399. XCSNET:    jz%mulga.oz@australia
  400. X
  401. XAny modifications received will be considered for a future release of
  402. Xvmail.  Of particular interest is SYS V compatibility and modifications
  403. Xto suit versions of MH to which I have no access.
  404. END_OF_READ_ME
  405. if test 4838 -ne `wc -c <READ_ME`; then
  406.     echo shar: \"READ_ME\" unpacked with wrong size!
  407. fi
  408. # end of overwriting check
  409. fi
  410. if test -f choose.c -a "${1}" != "-c" ; then 
  411.   echo shar: Will not over-write existing file \"choose.c\"
  412. else
  413. echo shar: Extracting \"choose.c\" \(6579 characters\)
  414. sed "s/^X//" >choose.c <<'END_OF_choose.c'
  415. X#ifndef lint
  416. Xstatic char *RCS_choose_c = "$Id: choose.c,v 1.2 90/04/23 14:40:52 rogers Exp $";
  417. X#endif
  418. X
  419. X/* --------------------
  420. X    vmail -- choose.c
  421. X
  422. X    Tty-based folder selection.
  423. X
  424. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  425. X-------------------- */
  426. X
  427. X#include "defs.h"
  428. X
  429. X#define START            10                /* offset from margin of screen */
  430. X#define RESET()            toggle=false,    /* left- or right- hand indicator */ \
  431. X                        i=FIRST+1,        /* initial row */                     \
  432. X                        j=START,        /* initial column */                 \
  433. X                        f=first            /* first folder */
  434. X
  435. XWINDOW    *chooser = (WINDOW *) NULL;
  436. X
  437. X/* --------------------
  438. X    Display folder selection page, read commands to move around page and
  439. X    select folders.
  440. X-------------------- */
  441. Xvoid
  442. Xchoose()
  443. X{
  444. X    int        n, i, j;
  445. X    bool    toggle;
  446. X    folder    next, f, showing(),
  447. X            first = folders,    /* first folder on screen */
  448. X            last;                /* folder after last folder on screen */
  449. X    char    c, str[LEN], flushin();
  450. X
  451. X    RESET();
  452. X    if(chooser == (WINDOW *) NULL)
  453. X        chooser = newwin(0, 0, 0, 0);
  454. X    last = showing(first);
  455. Xrestart:
  456. X    while((c = flushin()) != ' ' && c != 'q') switch(c) {
  457. X        case '\r':        /* go to next screen of folder names */
  458. X        case '\n':
  459. X            if(last == (folder) NULL)
  460. X                beep();
  461. X            else {
  462. X                first = last;
  463. X                last = showing(first);
  464. X                RESET();
  465. X            }
  466. X            break;
  467. X        case '\b':        /* go back one page of folders */
  468. X            if(first == folders)
  469. X                beep();
  470. X            else {
  471. X                for(i=(lines-FIRST)*2 ; i > FIRST && first->prev != (folder) NULL ; i--, first=first->prev)
  472. X                    ;
  473. X                last = showing(first);
  474. X                RESET();
  475. X            }
  476. X            break;
  477. X        case CTRL_L:    /* redraw */
  478. X            last = showing(first);
  479. X            break;
  480. X        case 'h':        /* move left */
  481. X            if(! toggle)    /* already at left */
  482. X                beep();
  483. X            else {
  484. X                next = f;
  485. X                FRST_OF_NAME(next);
  486. X                next = next->prev;
  487. X                if(next == (folder) NULL)
  488. X                    beep();
  489. X                else {
  490. X                    f = next; j = START; toggle = false;
  491. X                    (void)wmove(chooser, i, j);
  492. X                    (void)wrefresh(chooser);
  493. X                }
  494. X            }
  495. X            break;
  496. X        case 'j':        /* move down */
  497. X            if(i+1 >= lines)    /* at bottom */
  498. X                beep();
  499. X            else {
  500. X                next = f;
  501. X                for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
  502. X                    LAST_OF_NAME(next);
  503. X                    next = next->next;
  504. X                }
  505. X                if(next == (folder) NULL)
  506. X                    beep();
  507. X                else {
  508. X                    i++; f = next;
  509. X                    (void)wmove(chooser, i, j);
  510. X                    (void)wrefresh(chooser);
  511. X                }
  512. X            }
  513. X            break;
  514. X        case 'k':        /* move up */
  515. X            if(i <= FIRST+1)    /* at top */
  516. X                beep();
  517. X            else {
  518. X                next = f;
  519. X                for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
  520. X                    FRST_OF_NAME(next);
  521. X                    next = next->prev;
  522. X                }
  523. X                if(next == (folder) NULL)
  524. X                    beep();
  525. X                else {
  526. X                    i--; f = next;
  527. X                    (void)wmove(chooser, i, j);
  528. X                    (void)wrefresh(chooser);
  529. X                }
  530. X            }
  531. X            break;
  532. X        case 'l':        /* move right */
  533. X            if(toggle)        /* at right */
  534. X                beep();
  535. X            else {
  536. X                next = f;
  537. X                LAST_OF_NAME(next);
  538. X                next = next->next;
  539. X                if(next == (folder) NULL)
  540. X                    beep();
  541. X                else {
  542. X                    f = next; j = cols/2; toggle = true;
  543. X                    (void)wmove(chooser, i, j);
  544. X                    (void)wrefresh(chooser);
  545. X                }
  546. X            }
  547. X            break;
  548. X        default:
  549. X            beep();
  550. X            break;
  551. X    }
  552. X    if(c == ' ') {        /* attempt to go to folder */
  553. X        if(! f->valid) {    /* load folder */
  554. X            mvwaddstr(chooser, FIRST, 0, "Reading mail headers ...");
  555. X            (void)wmove(chooser, i, j);
  556. X            (void)wrefresh(chooser);
  557. X            f->valid = true;
  558. X            (void)find_mail(f, false);
  559. X        }
  560. X        if(f->valid == EMPTY) {        /* folder is empty */
  561. X                /* Go back to chooser, display "empty" message */
  562. X            (void)sprintf(str, "%s -- folder empty", f->name);
  563. X            if(first == f)        /* find new first folder for page */
  564. X                if(f->next != (folder) NULL)
  565. X                    first = f->next;
  566. X                else
  567. X                    first = folders;
  568. X            last = showing(first);
  569. X            RESET();
  570. X            mvwaddstr(chooser, FIRST, 0, str);
  571. X            (void)wmove(chooser, i, j);
  572. X            (void)wrefresh(chooser);
  573. X            goto restart;
  574. X        } 
  575. X        curflr = f;
  576. X        curmail = f->mail;
  577. X        y = FIRST;
  578. X    }
  579. X    display_page();
  580. X}
  581. X
  582. X
  583. X/* --------------------
  584. X    Show all folder names starting with "start" ending with last folder or
  585. X    when page is full.
  586. X-------------------- */
  587. Xfolder
  588. Xshowing(start)
  589. X    folder    start;
  590. X{
  591. X    int        count, i = FIRST+1, j = START;
  592. X    bool    toggle = false;
  593. X    folder    p, f;
  594. X    item    m;
  595. X    char    str[LEN];
  596. X
  597. X    (void)wclear(chooser);
  598. X    mvwaddstr(chooser, TITLE, 0,
  599. X"h,j,k,l -- left,down,up,right        <return>,<bs> -- next/prev page of folders");
  600. X    mvwaddstr(chooser, STATUS, 0,
  601. X"<space> -- select folder             q -- quit, no change         ^L -- refresh");
  602. X    for(p=f=start ; i < lines && f != (folder) NULL ; p=f=p->next) {
  603. X        if(f->valid) {
  604. X                /* find last page of folder, count items in folders */
  605. X            for(count=0, p=f ; p->next != (folder) NULL &&
  606. X                                        p->next->name == f->name ; p=p->next)
  607. X                for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  608. X                    ;
  609. X            for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  610. X                ;
  611. X            if(count == 1)
  612. X                (void)sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
  613. X            else
  614. X                (void)sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
  615. X                                                    p->last->number, count);
  616. X        } else
  617. X            (void)sprintf(str, "%-15s(inactive)", f->name);
  618. X        if(f == curflr) standout();
  619. X        mvwaddstr(chooser, i, j, str);
  620. X        if(f == curflr) standend();
  621. X        if(toggle)
  622. X            j = START, i++;
  623. X        else
  624. X            j = cols/2;
  625. X        toggle = ! toggle;
  626. X    }
  627. X    (void)wmove(chooser, FIRST+1, START);
  628. X    (void)wrefresh(chooser);
  629. X    return(f);
  630. X}
  631. X
  632. X
  633. XWINDOW *folwin = (WINDOW *) NULL;
  634. X
  635. X/* --------------------
  636. X    List all folders, active or otherwise.
  637. X-------------------- */
  638. Xvoid
  639. Xlist_folders()
  640. X{
  641. X    folder    f = folders, p;
  642. X    int        count, i = FIRST, half = cols/2;
  643. X    bool    toggle = false;
  644. X    char    str[LEN];
  645. X    WINDOW    *newwin();
  646. X    item    m;
  647. X
  648. X    if(folwin == (WINDOW *) NULL)
  649. X        folwin = newwin(0, 0, 0, 0);
  650. X    (void)wclear(folwin);
  651. X    for(p=f ; ; p=f=p->next) {
  652. X        if((i+2) % lines == 0) {
  653. X            if(use_prompt(folwin) == 'q')
  654. X                break;
  655. X            i = FIRST;
  656. X            (void)wclear(folwin);
  657. X        }
  658. X        if(f == (folder) NULL) {
  659. X            (void)use_prompt(folwin);
  660. X            break;
  661. X        }
  662. X        if(f->valid) {
  663. X                /* find last page of folder, count items in folders */
  664. X            for(count=0, p=f ; p->next != (folder) NULL &&
  665. X                                        p->next->name == f->name ; p=p->next)
  666. X                for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  667. X                    ;
  668. X            for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
  669. X                ;
  670. X            if(count == 1)
  671. X                (void)sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
  672. X            else
  673. X                (void)sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
  674. X                                                    p->last->number, count);
  675. X        } else
  676. X            (void)sprintf(str, "%-15s(inactive)", f->name);
  677. X        if(f == curflr)
  678. X            (void)wstandout(folwin);
  679. X        if(toggle) {
  680. X            mvwaddstr(folwin, i, half, str);
  681. X            i++;
  682. X        } else
  683. X            mvwaddstr(folwin, i, 10, str);
  684. X        if(f == curflr)
  685. X            (void)wstandend(folwin);
  686. X        toggle = !toggle;
  687. X    }
  688. X    display_page();
  689. X}
  690. END_OF_choose.c
  691. if test 6579 -ne `wc -c <choose.c`; then
  692.     echo shar: \"choose.c\" unpacked with wrong size!
  693. fi
  694. # end of overwriting check
  695. fi
  696. if test -f cmds.c -a "${1}" != "-c" ; then 
  697.   echo shar: Will not over-write existing file \"cmds.c\"
  698. else
  699. echo shar: Extracting \"cmds.c\" \(3678 characters\)
  700. sed "s/^X//" >cmds.c <<'END_OF_cmds.c'
  701. X#ifndef lint
  702. Xstatic char *RCS_cmds_c = "$Id: cmds.c,v 1.3 90/04/23 14:40:56 rogers Exp $";
  703. X#endif
  704. X
  705. X/* --------------------
  706. X    vmail -- cmds.c
  707. X
  708. X    Commands not included in page.c or move.c.
  709. X
  710. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  711. X-------------------- */
  712. X
  713. X#include "defs.h"
  714. X#include <signal.h>
  715. X
  716. X/* --------------------
  717. X    Print the name of the alternate folder.
  718. X-------------------- */
  719. Xvoid
  720. Xshow_folder()
  721. X{
  722. X    char    str[LEN];
  723. X
  724. X    if(alternate == (folder) NULL)
  725. X        addstatus("No alternate folder", false);
  726. X    else {
  727. X        (void)sprintf(str, "alternate folder is %s\n", alternate->name);
  728. X        addstatus(str, false);
  729. X    }
  730. X}
  731. X
  732. X
  733. X/* --------------------
  734. X    Make current folder inactive - remove list of mail headers, set valid
  735. X    to false.
  736. X-------------------- */
  737. Xvoid
  738. Xinactive()
  739. X{
  740. X    folder    f, p;
  741. X
  742. X        /* find first page of folder */
  743. X    p = curflr; FRST_OF_NAME(p);
  744. X        /* find last page of folder */
  745. X    f = curflr; LAST_OF_NAME(f);
  746. X    p->next = f->next;
  747. X    p->valid = false;
  748. X/* should free records */
  749. X    p->mail = p->last = (item) NULL;
  750. X    p->pagenum = p->pages = 1;
  751. X    if(p->next != (folder) NULL)
  752. X        p->next->prev = p;
  753. X    curflr = p;
  754. X    NEXT_VALID(curflr);
  755. X    if(curflr == (folder) NULL) {
  756. X        curflr = p;
  757. X        PREV_VALID(curflr);
  758. X    }
  759. X    if(curflr == (folder) NULL) {
  760. X        addstatus("Making last active folder inactive", true);
  761. X        to_normal();
  762. X        exit(0);
  763. X    } else {
  764. X        curmail = curflr->mail;
  765. X        y = FIRST;
  766. X        display_page();
  767. X    }
  768. X}
  769. X
  770. X
  771. X/* --------------------
  772. X    Show current mail item with fork to pager.
  773. X-------------------- */
  774. Xvoid
  775. Xshow_mail()
  776. X{
  777. X    sig_type    (*oldint)(), (*oldquit)(), (*signal())();
  778. X    char    str[LEN];
  779. X    union wait status;
  780. X
  781. X    clear();
  782. X    refresh();
  783. X    top_level = false;            /* used by tstp() so that right thing is done
  784. X                                   when process is restarted */
  785. X    if(! vfork()) {
  786. X        no_control();
  787. X        (void)sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
  788. X        execlp(pager, pager, str, 0);
  789. X        (void)printf("Warning: can't execute %s\n", pager);
  790. X        exit(0);
  791. X    }
  792. X    oldint = signal(SIGINT, SIG_IGN);
  793. X    oldquit = signal(SIGQUIT, SIG_IGN);
  794. X    (void)wait(&status);
  795. X    (void)signal(SIGINT, oldint);
  796. X    (void)signal(SIGQUIT, oldquit);
  797. X    top_level = true;
  798. X    to_control();
  799. X    hold_end();                    /* wait for user to want to continue - may wish
  800. X                                   to read error messages */
  801. X    display_page();
  802. X}
  803. X
  804. X
  805. X/* --------------------
  806. X    Save current mail item to named file.  If first non-space character
  807. X    is ~, expand it.
  808. X-------------------- */
  809. Xvoid
  810. Xsave_item()
  811. X{
  812. X    struct passwd *pwent, *getpwnam();
  813. X    char    *tmp, buf[LEN], *str = buf, save[LEN];
  814. X    FILE    *fi, *fo, *fopen();
  815. X
  816. X    (void)sprintf(save, "%s.%d", curflr->name, curmail->number);
  817. X    (void)sprintf(str, "file (%s)? ", save);
  818. X    get_string(str, str);
  819. X    for(; *str == ' ' ; str++)
  820. X        ;
  821. X    for(tmp=str ; *tmp != '\0' && *tmp != ' ' ; tmp++)
  822. X        ;
  823. X    *tmp = '\0';
  824. X    if(*str != '\0')        /* don't take default */
  825. X        if(*str == '~')    {    /* expand home directory name */
  826. X            tmp = str + 2;
  827. X            if(*(str+1) == '/')
  828. X                pwent = getpwnam(user);
  829. X            else {    
  830. X                for( ; *tmp != '\0' && *tmp != '/' ; tmp++)
  831. X                    ;
  832. X                *(tmp++) = '\0';
  833. X                if((pwent = getpwnam(str+1)) == (struct passwd *) NULL) {
  834. X                    (void)sprintf(save, "%s: no such user", str+1);
  835. X                    addstatus(save, true);
  836. X                    return;
  837. X                }
  838. X            }
  839. X            (void)sprintf(save, "%s/%s", pwent->pw_dir, tmp);
  840. X        } else                /* take str as given */
  841. X            (void)strcpy(save, str);
  842. X    if((fo = fopen(save, "w")) == (FILE *) NULL) {
  843. X        (void)sprintf(str, "%s: no write permission", save);
  844. X        addstatus(str, true);
  845. X        return;
  846. X    }
  847. X    addstatus("saving ...", false);
  848. X    (void)sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
  849. X    fi = fopen(str, "r");
  850. X    while(fgets(str, LEN, fi) != (char *) NULL)
  851. X        (void)fprintf(fo, "%s", str);
  852. X    (void)fclose(fi); (void)fclose(fo);
  853. X    addstatus("saved", false);
  854. X}
  855. END_OF_cmds.c
  856. if test 3678 -ne `wc -c <cmds.c`; then
  857.     echo shar: \"cmds.c\" unpacked with wrong size!
  858. fi
  859. # end of overwriting check
  860. fi
  861. if test -f defs.h -a "${1}" != "-c" ; then 
  862.   echo shar: Will not over-write existing file \"defs.h\"
  863. else
  864. echo shar: Extracting \"defs.h\" \(4971 characters\)
  865. sed "s/^X//" >defs.h <<'END_OF_defs.h'
  866. X#ifndef lint
  867. Xstatic char *RCS_defs_h = "$Id: defs.h,v 1.8 90/09/19 13:55:10 rogers Exp $";
  868. X#endif
  869. X
  870. X/* --------------------
  871. X    vmail -- defs.h
  872. X
  873. X    Interactive screen-based mail handler that sits on top of MH.
  874. X
  875. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  876. X-------------------- */
  877. X
  878. X#include <stdio.h>
  879. X#include <string.h>
  880. X#ifdef sun
  881. X#include <malloc.h>
  882. Xextern char *memalign();
  883. X#else
  884. Xextern char *malloc();
  885. Xextern char *realloc();
  886. X#endif
  887. X#include <pwd.h>
  888. X#include <setjmp.h>
  889. X#include <sgtty.h>
  890. X#include <sys/types.h>
  891. X#include <sys/wait.h>
  892. X#include <sys/dir.h>
  893. X#include <sys/file.h>
  894. X#include <sys/stat.h>
  895. X#include <curses.h>
  896. X
  897. X/*
  898. X * MH utilities needed by vmail
  899. X */
  900. X#define BURST        "burst"
  901. X#define COMP        "comp"
  902. X#define DIST        "dist"
  903. X#define FORW        "forw"
  904. X#define INC            "inc"
  905. X#define REPL        "repl"
  906. X#define SORTM        "sortm"
  907. X
  908. X/*
  909. X * Other things
  910. X */
  911. X
  912. X#if defined(sun) || defined(ultrix)
  913. X#define    sig_type    void        /* Suns and Ultrix 3.x            */
  914. X#else
  915. Xtypedef    int        sig_type;    /* the rest of the world        */
  916. X#endif
  917. X
  918. X#define PAGER        "more"            /* default pager */
  919. X#define EDITOR        "vi"            /* default editor */
  920. X#define SHELL        "/bin/csh"        /* default shell */
  921. X#define CAT            "/bin/cat"        /* used as `show' for pipes */
  922. X
  923. X#define LEN            255                        /* standard string length */
  924. X#define MAXITEMS    4097                    /* number of items in folder */
  925. X#define FPROT        0755                    /* standard file protection */
  926. X#define TITLE        0                        /* title line */
  927. X#define STATUS        1                        /* status line */
  928. X#define FIRST        2                        /* first line of info */
  929. X#define PROFILE        ".mh_profile"            /* default profile */
  930. X#define CURFOL        "inbox"                    /* default current folder */
  931. X#define CONTEXT        "context"                /* default context file */
  932. X#define SEQU        ".mh_sequences"            /* default .mh_sequences file */
  933. X#define MAILDIR        "Mail"                    /* default mail directory */
  934. X
  935. X#define    true        1
  936. X#define false        0
  937. X#define EMPTY        2                        /* used to mark empty folders */
  938. X#define CTRL_L        '\014'
  939. X#define CTRL_R        '\022'
  940. X#define ESC            '\033'
  941. X#define DEL            '\177'
  942. X
  943. X/* --------------------
  944. X    Data structures.
  945. X
  946. X    Each folder is divided into pages of (_lines_-2) mail items, _lines_
  947. X    being the number of lines for the tty type.  Pages of folders are
  948. X    stored in a doubly-linked list of pages (struct mail_folder), mail
  949. X    items (struct mail_item) in doubly liked lists of mail.  Folders are
  950. X    sorted alphabetically, and pages of mail items are sorted numerically.
  951. X-------------------- */
  952. Xstruct mail_item {
  953. X    int        number;                        /* number of item */
  954. X    char    *title;                        /* header */
  955. X    struct mail_item *next, *prev;        /* links to other headers */
  956. X};
  957. Xtypedef struct mail_item *item;
  958. X
  959. Xstruct mail_folder {
  960. X    char    *name;                        /* folder name */
  961. X    int        pages, pagenum;                /* no. of pages, no. of page */
  962. X    bool    valid;                        /* true if folder active */
  963. X    item    mail, last;                    /* first and last mail items for page
  964. X                                           - NULL if folder not active */
  965. X    struct mail_folder *next, *prev;    /* linked list of folders */
  966. X};
  967. Xtypedef struct mail_folder *folder;
  968. X
  969. X
  970. Xextern folder    folders,                /* list of all folders */
  971. X                curflr,                    /* current folder */
  972. X                alternate;                /* alternate folder */
  973. Xextern item        curmail;                /* current mail */
  974. Xextern char        **environ,
  975. X                *user,                    /* user name */
  976. X                *pager,                    /* desired pager */
  977. X                *editor,                /* desired editor */
  978. X                *shell,                    /* desired shell */
  979. X                *mail_dir,                /* mail directory */
  980. X                *context;                /* context file */
  981. Xextern int        y,                        /* current Y co-ordinate (for curses) */
  982. X                folder_protect,            /* protection for folders */
  983. X                lines,                    /* lines per screen */
  984. X                cols;                    /* cols per screen */
  985. Xextern bool        top_level,                /* flag used to see if process stopped
  986. X                                           from within subprocess */
  987. X                do_flush,                /* true if input is to be flushed */
  988. X                comp_args,                /* true if calls to comp needs args */
  989. X                repl_args,                /* true if calls to repl needs args */
  990. X                forw_args,                /* true if calls to forw needs args */
  991. X                burst_args,                /* true if calls to burst needs args */
  992. X                dist_args,                /* true if calls to dist needs args */
  993. X                sort_args;                /* true if calls to sortm needs args */
  994. Xextern jmp_buf    env;
  995. X
  996. X#include "macro.h"
  997. X
  998. Xfolder find_mail();
  999. Xextern char *sprintf();
  1000. Xvoid    add_page_header(), addstatus(), choose(), comp(), create_mail_record(),
  1001. X        cursor_down(), cursor_up(),
  1002. X        display_page(), delete_item(), deleteline(), edit(),
  1003. X        find_folders(), flatten(), forw(), get_env(),
  1004. X        get_home(), read_profile(), get_string(), get_title(),
  1005. X        goto_folder(), call_shell(), goto_incorp_folder(),
  1006. X        goto_next_folder(), goto_prev_folder(), hold_end(),
  1007. X        inactive(), inc(), init(), list_folders(),
  1008. X        mark_valid_folders(), move_item(), next_page(),
  1009. X        no_control(), pack_folder(), prev_page(), repl(),
  1010. X        refresh_folder(), save_item(), search(), show_folder(),
  1011. X        show_mail(), show_title(), to_control(), to_normal(),
  1012. X        undo(), pack(), cursor_first(), cursor_middle(),
  1013. X        cursor_last(), goto_first_page(), goto_last_page(),
  1014. X        squash(), get_date(), process_args(), do_pipe(),
  1015. X        sort_folder(), burst_item(), dist_item();
  1016. Xbool change_item();
  1017. END_OF_defs.h
  1018. if test 4971 -ne `wc -c <defs.h`; then
  1019.     echo shar: \"defs.h\" unpacked with wrong size!
  1020. fi
  1021. # end of overwriting check
  1022. fi
  1023. if test -f find.c -a "${1}" != "-c" ; then 
  1024.   echo shar: Will not over-write existing file \"find.c\"
  1025. else
  1026. echo shar: Extracting \"find.c\" \(1985 characters\)
  1027. sed "s/^X//" >find.c <<'END_OF_find.c'
  1028. X#ifndef lint
  1029. Xstatic char *RCS_find_c = "$Id: find.c,v 1.2 90/04/23 14:41:04 rogers Exp $";
  1030. X#endif
  1031. X
  1032. X/* --------------------
  1033. X    vmail -- find.c
  1034. X
  1035. X    Searching titles for strings.
  1036. X
  1037. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  1038. X-------------------- */
  1039. X
  1040. X#include "defs.h"
  1041. X
  1042. Xstatic char str[LEN] = "^.*";
  1043. X
  1044. X/* --------------------
  1045. X    Get string for searching, either forwards (forwards = true) or backwards
  1046. X    (forwards = false).  Then scan mail headers using regex().
  1047. X-------------------- */
  1048. Xvoid
  1049. Xsearch(forwards)
  1050. X    int        forwards;
  1051. X{
  1052. X    char    s1[LEN], *s2, *re_comp();
  1053. X    int        i;
  1054. X    bool    found = false;
  1055. X    folder    f;
  1056. X    item    m;
  1057. X
  1058. X    get_string((forwards) ? "/" : "?", s1);
  1059. X    if((i = strlen(s1)) > 0) {
  1060. X            /* new search string */
  1061. X        (void)strcpy(str+3, s1);
  1062. X        str[i+=3] = '.', str[++i] = '*', str[++i] = '\0';
  1063. X    } else if(strlen(str+3) == 0) {
  1064. X        addstatus("", false);
  1065. X        return;
  1066. X    }
  1067. X    if((s2 = re_comp(str)) != (char *) NULL) {
  1068. X        addstatus(s2, false);
  1069. X        return;
  1070. X    }
  1071. X    addstatus("searching ...", false);
  1072. X    if(forwards)
  1073. X        for(i=y+1, f=curflr, m=curmail->next ; ! found && m != curmail ; ) {
  1074. X            if(m == (item) NULL) {
  1075. X                f = f->next; NEXT_VALID(f);
  1076. X                if(f == (folder) NULL) {
  1077. X                    f = folders;
  1078. X                    NEXT_VALID(f);
  1079. X                }
  1080. X                m = f->mail;
  1081. X                i = FIRST;
  1082. X            }
  1083. X            if(! (found = re_exec(m->title)))
  1084. X                m = m->next, i++;
  1085. X        }
  1086. X    else
  1087. X        for(i=y-1, f=curflr, m=curmail->prev ; ! found && m != curmail ; ) {
  1088. X            if(m == (item) NULL) {
  1089. X                f = f->prev; PREV_VALID(f);
  1090. X                if(f == (folder) NULL) {
  1091. X                        /* find last folder */
  1092. X                    for(f=folders ; f->next != (folder) NULL ; f=f->next)
  1093. X                        ;
  1094. X                    PREV_VALID(f);
  1095. X                }
  1096. X                    /* find last mail item with count */
  1097. X                for(i=FIRST, m=f->mail ; m->next != (item) NULL ; i++,m=m->next)
  1098. X                    ;
  1099. X            }
  1100. X            if(! (found = re_exec(m->title)))
  1101. X                m = m->prev, i--;
  1102. X        }
  1103. X    curmail = m, y = i;
  1104. X    if(f != curflr) {
  1105. X        curflr = f;
  1106. X        display_page();
  1107. X    } else if(! found)    /* come back to current folder (known to be valid) */
  1108. X        addstatus("pattern not found", true);
  1109. X    else
  1110. X        addstatus("", false);
  1111. X}
  1112. END_OF_find.c
  1113. if test 1985 -ne `wc -c <find.c`; then
  1114.     echo shar: \"find.c\" unpacked with wrong size!
  1115. fi
  1116. # end of overwriting check
  1117. fi
  1118. if test -f inc.c -a "${1}" != "-c" ; then 
  1119.   echo shar: Will not over-write existing file \"inc.c\"
  1120. else
  1121. echo shar: Extracting \"inc.c\" \(3762 characters\)
  1122. sed "s/^X//" >inc.c <<'END_OF_inc.c'
  1123. X#ifndef lint
  1124. Xstatic char *RCS_inc_c = "$Id: inc.c,v 1.3 90/04/23 14:41:07 rogers Exp $";
  1125. X#endif
  1126. X
  1127. X/* --------------------
  1128. X    vmail -- inc.c
  1129. X
  1130. X    Incorporate new mail with "inc", parse output and update appropriate
  1131. X    folder-pages.
  1132. X
  1133. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  1134. X-------------------- */
  1135. X
  1136. X#include "defs.h"
  1137. X
  1138. X#define INCORP        "Incorporating new mail into "
  1139. X#define TAIL        "...\n"
  1140. X
  1141. Xstatic folder isfol;        /* folder into which mail is being incorporated */
  1142. Xstatic item ismail;            /* last item of mail on isfol page */
  1143. Xstatic int count;            /* number of items on isfol page */
  1144. X
  1145. X/* --------------------
  1146. X    Call, inc, parse output to work out what items have been read and into
  1147. X    what folders.
  1148. X-------------------- */
  1149. Xvoid
  1150. Xinc()
  1151. X{
  1152. X    char    str[LEN], line[LEN], *tmp, *fgets();
  1153. X    FILE    *pp, *fdopen();
  1154. X    int        num, pd[2], len = strlen(INCORP), numbers();
  1155. X    bool    redraw = true;
  1156. X    union wait status;
  1157. X
  1158. X    addstatus("incorporating mail ... ", true);
  1159. X    (void)pipe(pd);
  1160. X    if(! vfork()) {
  1161. X        (void)close(pd[0]);
  1162. X        (void)dup2(pd[1], 1);
  1163. X        (void)close(pd[1]);
  1164. X        (void)dup2(1, 2);
  1165. X        execlp(INC, "inc", 0);
  1166. X    }
  1167. X    (void)close(pd[1]);
  1168. X    if((pp = fdopen(pd[0], "r")) == (FILE *) NULL) {
  1169. X        addstatus("panic, can't incorporate mail", true);
  1170. X        return;
  1171. X    }
  1172. X    while((tmp = fgets(str, LEN, pp)) != (char *) NULL)    /* read "inc" output */
  1173. X        if(strncmp(tmp, INCORP, len) == 0) {    /* reading into new folder */
  1174. X            tmp += len;
  1175. X            tmp[strlen(tmp)-strlen(TAIL)] = '\0';
  1176. X            goto_incorp_folder(tmp);
  1177. X            if(isfol == (folder) NULL) {
  1178. X                (void)sprintf(line, "can't go to folder %s", tmp);
  1179. X                addstatus(line, true);
  1180. X                redraw = false;
  1181. X                break;
  1182. X            } else {
  1183. X                (void)sprintf(line, "incorporating mail into folder %s", tmp);
  1184. X                addstatus(line, true);
  1185. X            }
  1186. X        } else if(num = numbers(tmp))    /* continuing to read into folder */
  1187. X            create_mail_record(num);
  1188. X        else if(strlen(str) > 2) {        /* vmail is confused - break */
  1189. X            str[strlen(str)-1] = '\0';
  1190. X            addstatus(str, true);
  1191. X            redraw = false;
  1192. X            break;
  1193. X        }
  1194. X    if(redraw) {
  1195. X        if(isfol != curflr)
  1196. X            alternate = curflr;
  1197. X        curflr = isfol;
  1198. X        curmail = ismail;
  1199. X        y = count;
  1200. X        display_page();
  1201. X    }
  1202. X    (void)fclose(pp);
  1203. X    (void)wait(&status);
  1204. X}
  1205. X
  1206. X
  1207. X/* --------------------
  1208. X    Extract the first number from str.
  1209. X-------------------- */
  1210. Xint
  1211. Xnumbers(str)
  1212. X    char    *str;
  1213. X{
  1214. X    char    save, *tmp;
  1215. X    int        i;
  1216. X
  1217. X    for(; *str == ' ' ; str++)
  1218. X        ;
  1219. X    for(tmp=str ; *str >= '0' && *str <= '9' ; str++)
  1220. X        ;
  1221. X    save = *str, *str = '\0', i = atoi(tmp), *str = save;
  1222. X    return(i);
  1223. X}
  1224. X
  1225. X
  1226. X/* --------------------
  1227. X    Find the folder into which mail is being incorporated, set isfol,
  1228. X    ismail, count.
  1229. X-------------------- */
  1230. Xvoid
  1231. Xgoto_incorp_folder(str)
  1232. X    char    *str;
  1233. X{
  1234. X    folder    create_folder();
  1235. X
  1236. X    GOTO_NAME(isfol, str);
  1237. X    if(isfol == (folder) NULL) {    /* new folder */
  1238. X        isfol = create_folder(str);
  1239. X        isfol->valid = true;
  1240. X        ismail = (item) NULL;
  1241. X        count = FIRST-1;
  1242. X    } else {
  1243. X        if(! isfol->valid) {
  1244. X            isfol->valid = true;
  1245. X            (void)find_mail(isfol, false);
  1246. X        }
  1247. X            /* find last appropriate folder record */
  1248. X        LAST_OF_NAME(isfol);
  1249. X        for(count=FIRST, ismail=isfol->mail ; ismail->next != (item) NULL ;
  1250. X                                                count++, ismail=ismail->next)
  1251. X            ;
  1252. X    }
  1253. X}
  1254. X
  1255. X
  1256. X/* --------------------
  1257. X    Create and insert new item record into isfol, may need to create new page.
  1258. X-------------------- */
  1259. Xvoid
  1260. Xcreate_mail_record(num)
  1261. X    int        num;
  1262. X{
  1263. X    item    m;
  1264. X    folder    new_folder();
  1265. X
  1266. X    m = NEW(mail_item);
  1267. X    get_title(isfol, m, num);
  1268. X    m->next = (item) NULL;
  1269. X    if(count > lines) {
  1270. X            /* create new folder record */
  1271. X        isfol = new_folder(isfol);
  1272. X        ismail = (item) NULL;
  1273. X        count = FIRST;
  1274. X    } else
  1275. X        count++;
  1276. X    if(ismail == (item) NULL) {
  1277. X            /* new record, possibly new folder */
  1278. X        m->prev = (item) NULL;
  1279. X        isfol->mail = isfol->last = m;
  1280. X    } else {
  1281. X            /* insert at end of list of mail items */
  1282. X        m->prev = ismail;
  1283. X        ismail->next = isfol->last = m;
  1284. X    }
  1285. X    ismail = m;
  1286. X}
  1287. END_OF_inc.c
  1288. if test 3762 -ne `wc -c <inc.c`; then
  1289.     echo shar: \"inc.c\" unpacked with wrong size!
  1290. fi
  1291. # end of overwriting check
  1292. fi
  1293. if test -f low.c -a "${1}" != "-c" ; then 
  1294.   echo shar: Will not over-write existing file \"low.c\"
  1295. else
  1296. echo shar: Extracting \"low.c\" \(3352 characters\)
  1297. sed "s/^X//" >low.c <<'END_OF_low.c'
  1298. X#ifndef lint
  1299. Xstatic char *RCS_low_c = "$Id: low.c,v 1.3 90/04/23 14:41:24 rogers Exp $";
  1300. X#endif
  1301. X
  1302. X/* --------------------
  1303. X    vmail -- low.c
  1304. X
  1305. X    Low level screen update and data structure update routines, other
  1306. X    similar stuff.
  1307. X
  1308. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  1309. X-------------------- */
  1310. X
  1311. X#include "defs.h"
  1312. X
  1313. X/* --------------------
  1314. X    Get string from terminal (visibly).
  1315. X-------------------- */
  1316. Xvoid
  1317. Xget_string(mes, str)
  1318. X    char    *mes, *str;
  1319. X{
  1320. X    char    c;
  1321. X    int        i;
  1322. X
  1323. X    move(STATUS, 0);
  1324. X    clrtoeol();
  1325. X    addstr(mes);
  1326. X    refresh();
  1327. X    for(i=0 ; (c = getchar()) != '\n' && c != '\r' && c != ESC ; )
  1328. X        if(i > 0 && c == '\b') {
  1329. X            i--;
  1330. X            mvaddch(STATUS, strlen(mes)+i, ' ');
  1331. X            move(STATUS, strlen(mes)+i);
  1332. X            refresh();
  1333. X        } else if(c != '\b') {
  1334. X            str[i++] = c;
  1335. X            addch(c);
  1336. X            refresh();
  1337. X        }
  1338. X    str[i] = '\0';
  1339. X    move(y, 0);
  1340. X}
  1341. X
  1342. X
  1343. X/* --------------------
  1344. X    Put string on status line.
  1345. X-------------------- */
  1346. Xvoid
  1347. Xaddstatus(str, stand)
  1348. X    char    *str;
  1349. X    bool    stand;
  1350. X{
  1351. X    move(STATUS, 0);
  1352. X    clrtoeol();
  1353. X    if(stand)
  1354. X        standout();        /* doesn't do anything? */
  1355. X    addstr(str);
  1356. X    if(stand)
  1357. X        standend();
  1358. X    move(y, 0);
  1359. X    refresh();
  1360. X}
  1361. X
  1362. X
  1363. X/* --------------------
  1364. X    Fudge deleteline because curses wont delete the line immediately
  1365. X    after a ^Z, and because it doesnt clear the last line of the screen.
  1366. X-------------------- */
  1367. Xvoid
  1368. Xdeleteline()
  1369. X{
  1370. X    mvaddstr(y, 0, "scribble");
  1371. X    deleteln();
  1372. X    move(FIRST+lines-1, 0);
  1373. X    clrtoeol();
  1374. X    move(y, 0);
  1375. X}
  1376. X
  1377. X
  1378. Xint
  1379. Xputch(c)
  1380. X    char    c;
  1381. X{
  1382. X    return(putchar(c));    /* turn macro into routine */
  1383. X}
  1384. X
  1385. X
  1386. X/* --------------------
  1387. X    Put prompt on screen, wait for getchar().
  1388. X-------------------- */
  1389. Xint
  1390. Xuse_prompt(win)
  1391. X    WINDOW    *win;
  1392. X{
  1393. X    int        c = (cols-42)/2;
  1394. X
  1395. X    mvwaddstr(win,FIRST+lines-1,c,"-- hit space to continue, q to quit -- ");
  1396. X    (void)wrefresh(win);
  1397. X    return(getchar());
  1398. X}
  1399. X
  1400. X
  1401. X/* --------------------
  1402. X    Put info for mail item on screen at row i.
  1403. X-------------------- */
  1404. Xvoid
  1405. Xshow_title(str, i, mail)
  1406. X    char    *str;
  1407. X    int        i;
  1408. X    item    mail;
  1409. X{
  1410. X    (void)sprintf(str, "%4d%s", mail->number, mail->title);
  1411. X    mvaddstr(i, 0, str);
  1412. X}
  1413. X
  1414. X
  1415. X/* --------------------
  1416. X    Put header for page at top of screen.
  1417. X-------------------- */
  1418. Xvoid
  1419. Xadd_page_header(str)
  1420. X    char    *str;
  1421. X{
  1422. X    (void)sprintf(str, "%s (page %d of %d) - Type 'h' for help ", curflr->name, curflr->pagenum,
  1423. X                                                            curflr->pages);
  1424. X    mvaddstr(TITLE, 0, str);
  1425. X}
  1426. X
  1427. X
  1428. X/* --------------------
  1429. X    Flush typeahead.
  1430. X-------------------- */
  1431. Xchar
  1432. Xflushin()
  1433. X{
  1434. X    struct sgttyb sg;
  1435. X
  1436. X    if(do_flush) {
  1437. X        (void)ioctl(0, TIOCGETP, (caddr_t)&sg);
  1438. X        (void)ioctl(0, TIOCSETP, (caddr_t)&sg);
  1439. X    }
  1440. X    return(getchar());
  1441. X}
  1442. X
  1443. X
  1444. X/* --------------------
  1445. X    Print message, wait for getchar();
  1446. X-------------------- */
  1447. Xvoid
  1448. Xhold_end()
  1449. X{
  1450. X    tputs(SO, 1, putch);
  1451. X    (void)printf("-- any character to continue --");
  1452. X    tputs(SE, 1, putch);
  1453. X    (void)fflush(stdout);
  1454. X    (void)getchar();
  1455. X}
  1456. X
  1457. X
  1458. X#define ctol(c)        (((c) >= 'A' && (c) <= 'Z') ? c-'A'+'a' : c)
  1459. X
  1460. X/* --------------------
  1461. X    Case independent strncmp.
  1462. X-------------------- */
  1463. Xlstrncmp(s1, s2, n)
  1464. X    char *s1, *s2;
  1465. X    int n;
  1466. X{
  1467. X    for( ; ctol(*s1) == ctol(*s2) && n > 0 ; s1++, s2++, n--)
  1468. X        ;
  1469. X    return((n > 0) ? *s1 - *s2 : 0);
  1470. X}
  1471. X
  1472. X
  1473. X/* --------------------
  1474. X    String processing - more useful form of index.
  1475. X    Skip current non-white then skip white, replacing by null.
  1476. X-------------------- */
  1477. Xchar *
  1478. Xnext_token(t)
  1479. X    char    *t;
  1480. X{
  1481. X    for( ; *t != ' ' && *t != '\t' && *t != '\0' ; t++)
  1482. X        ;
  1483. X    for( ; *t == ' ' || *t == '\t' ; t++)
  1484. X        *t = '\0';
  1485. X    return(t);
  1486. X}
  1487. END_OF_low.c
  1488. if test 3352 -ne `wc -c <low.c`; then
  1489.     echo shar: \"low.c\" unpacked with wrong size!
  1490. fi
  1491. # end of overwriting check
  1492. fi
  1493. if test -f macro.h -a "${1}" != "-c" ; then 
  1494.   echo shar: Will not over-write existing file \"macro.h\"
  1495. else
  1496. echo shar: Extracting \"macro.h\" \(1229 characters\)
  1497. sed "s/^X//" >macro.h <<'END_OF_macro.h'
  1498. X#ifndef lint
  1499. Xstatic char *RCS_macro_h = "$Id: macro.h,v 1.2 90/04/23 14:41:27 rogers Exp $";
  1500. X#endif
  1501. X
  1502. X/* --------------------
  1503. X    macro.h -- assorted functions
  1504. X
  1505. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  1506. X-------------------- */
  1507. X
  1508. X/*
  1509. X * functions for allocating memory.  Note that on sparc implementations,
  1510. X * we use memalign for mallocing structs, as it is less likely to
  1511. X * return a bad pointer.
  1512. X */
  1513. X
  1514. X#define beep()        (void)printf("%c", 007)
  1515. X#define NEWSTR(N)    (char *) malloc((unsigned)(N))
  1516. X#ifdef sparc
  1517. X#define NEW(S)        (struct S *) memalign((unsigned)8,(unsigned)sizeof(struct S))
  1518. X#else
  1519. X#define NEW(S)        (struct S *) malloc((unsigned)sizeof(struct S))
  1520. X#endif
  1521. X
  1522. X/* --------------------
  1523. X    Moving between pages of mail items.
  1524. X-------------------- */
  1525. X#define PREV_VALID(F)    for(; F != (folder) NULL && ! F->valid ; F=F->prev)
  1526. X#define NEXT_VALID(F)    for(; F != (folder) NULL && ! F->valid ; F=F->next)
  1527. X#define FRST_OF_NAME(F)    for(; F->prev != (folder) NULL && \
  1528. X                                F->name == F->prev->name ; F=F->prev)
  1529. X#define LAST_OF_NAME(F)    for(; F->next != (folder) NULL && \
  1530. X                                F->name == F->next->name ; F=F->next)
  1531. X#define GOTO_NAME(F,S)    for(F=folders ; F != (folder) NULL && \
  1532. X                                strcmp(S, F->name) != 0 ; F=F->next)
  1533. END_OF_macro.h
  1534. if test 1229 -ne `wc -c <macro.h`; then
  1535.     echo shar: \"macro.h\" unpacked with wrong size!
  1536. fi
  1537. # end of overwriting check
  1538. fi
  1539. if test -f page.c -a "${1}" != "-c" ; then 
  1540.   echo shar: Will not over-write existing file \"page.c\"
  1541. else
  1542. echo shar: Extracting \"page.c\" \(8170 characters\)
  1543. sed "s/^X//" >page.c <<'END_OF_page.c'
  1544. X#ifndef lint
  1545. Xstatic char *RCS_page_c = "$Id: page.c,v 1.2 90/04/23 14:41:42 rogers Exp $";
  1546. X#endif
  1547. X
  1548. X/* --------------------
  1549. X    vmail -- page.c
  1550. X
  1551. X    Routines for paging between folders.
  1552. X
  1553. X    Copyright (C) J. Zobel, University of Melbourne, October 1987.
  1554. X-------------------- */
  1555. X
  1556. X#include "defs.h"
  1557. X
  1558. X/* --------------------
  1559. X    Clear screen, show current page of mail items.
  1560. X-------------------- */
  1561. Xvoid
  1562. Xdisplay_page()
  1563. X{
  1564. X    int        i;
  1565. X    item    mail;
  1566. X    char    str[LEN];
  1567. X
  1568. X    clear();
  1569. X    add_page_header(str);
  1570. X    for(i=FIRST, mail=curflr->mail ; mail != (item) NULL ; i++, mail=mail->next)
  1571. X        show_title(str, i, mail);
  1572. X    move(y, 0);
  1573. X    refresh();
  1574. X}
  1575. X
  1576. X
  1577. X/* --------------------
  1578. X    Find previous valid page of mail items (times count).
  1579. X-------------------- */
  1580. Xvoid
  1581. Xprev_page(count, display)
  1582. X    int        count;
  1583. X    bool    display;
  1584. X{
  1585. X    bool    show = false;
  1586. X    folder    f, p = curflr;
  1587. X
  1588. X    for( ; count > 0 ; count--) {
  1589. X        f = curflr->prev; PREV_VALID(f);
  1590. X        if(f == (folder) NULL)
  1591. X            break;
  1592. X        else {
  1593. X            show = true;
  1594. X            y = FIRST;
  1595. X            curflr = f;
  1596. X            curmail = curflr->mail;
  1597. X        }
  1598. X    }
  1599. X    if(p != curflr)
  1600. X        alternate = p;
  1601. X    if(display) {
  1602. X        if(show)
  1603. X            display_page();
  1604. X        if(f == (folder) NULL)
  1605. X            addstatus("first active page", true);
  1606. X    }
  1607. X}
  1608. X
  1609. X
  1610. X/* --------------------
  1611. X    Find next valid page of mail items (times count).
  1612. X-------------------- */
  1613. Xvoid
  1614. Xnext_page(count, display)
  1615. X    int        count;
  1616. X    bool    display;
  1617. X{
  1618. X    bool    show = false;
  1619. X    folder    f, p = curflr;
  1620. X
  1621. X    for( ; count > 0 ; count--) {
  1622. X        f = curflr->next; NEXT_VALID(f);
  1623. X        if(f == (folder) NULL)
  1624. X            break;
  1625. X        else {
  1626. X            show = true;
  1627. X            y = FIRST;
  1628. X            curflr = f;
  1629. X            curmail = curflr->mail;
  1630. X        }
  1631. X    }
  1632. X    if(p != curflr)
  1633. X        alternate = p;
  1634. X    if(display) {
  1635. X        if(show)
  1636. X            display_page();
  1637. X        if(f == (folder) NULL)
  1638. X            addstatus("last active page", true);
  1639. X    }
  1640. X}
  1641. X
  1642. X
  1643. X/* --------------------
  1644. X    Move cursor up count lines.
  1645. X-------------------- */
  1646. Xvoid
  1647. Xcursor_up(count)
  1648. X    int count;
  1649. X{
  1650. X    bool    redraw = false;
  1651. X
  1652. X    addstatus("", false);                /* clear status line */
  1653. X    for( ; count > 0 ; count--)
  1654. X        if(curmail->prev == (item) NULL) {
  1655. X            if(curflr->prev == (folder) NULL ||
  1656. X                                    curflr->name != curflr->prev->name) {
  1657. X                addstatus("first page of folder", true);
  1658. X                break;
  1659. X            } else {
  1660. X                redraw = true;
  1661. X                prev_page(1, false);
  1662. X                    /* find last mail item on page */
  1663. X                for( ; curmail->next != (item) NULL ; y++)
  1664. X                    curmail=curmail->next;
  1665. X            }
  1666. X        } else {
  1667. X            y--;
  1668. X            curmail = curmail->prev;
  1669. X        }
  1670. X    if(redraw)
  1671. X        display_page();
  1672. X    else {
  1673. X        move(y, 0);
  1674. X        refresh();
  1675. X    }
  1676. X}
  1677. X
  1678. X
  1679. X/* --------------------
  1680. X    Move cursor down count lines.
  1681. X-------------------- */
  1682. Xvoid
  1683. Xcursor_down(count)
  1684. X    int        count;
  1685. X{
  1686. X    bool    redraw = false;
  1687. X
  1688. X    addstatus("", false);                /* clear status line */
  1689. X    for( ; count > 0 ; count--)
  1690. X        if(curmail->next == (item) NULL) {
  1691. X            if(curflr->next == (folder) NULL ||
  1692. X                                    curflr->name != curflr->next->name) {
  1693. X                addstatus("last page of folder", true);
  1694. X                break;
  1695. X            } else {
  1696. X                redraw = true;
  1697. X                next_page(1, false);
  1698. X            }
  1699. X        } else {
  1700. X            y++;
  1701. X            curmail = curmail->next;
  1702. X        }
  1703. X    if(redraw)
  1704. X        display_page();
  1705. X    else {
  1706. X        move(y, 0);
  1707. X        refresh();
  1708. X    }
  1709. X}
  1710. X
  1711. X
  1712. X/* --------------------
  1713. X    Go to next folder, make active if not so already.
  1714. X-------------------- */
  1715. Xvoid
  1716. Xgoto_next_folder(count)
  1717. X    int        count;
  1718. X{
  1719. X    bool    changed = false;
  1720. X    folder    f, p = curflr;
  1721. X
  1722. X    for( ; count > 0 ; count--) {
  1723. X            /* skip other pages of current folder */
  1724. X        for(f=p ; p->next != (folder) NULL && p->next->name == f->name ;
  1725. X            p=p->next)
  1726. X            ;
  1727. X        if(p->next == (folder) NULL) {
  1728. X            addstatus("last folder", true);
  1729. X            break;
  1730. X        } else {
  1731. X            changed = true;
  1732. X            p = p->next;
  1733. X        }
  1734. X    }
  1735. X    if(changed) {
  1736. X        do {
  1737. X            if(!p->valid) {
  1738. X                p->valid = true;
  1739. X                addstatus("reading mail headers ...", true);
  1740. X                (void)find_mail(p, false);
  1741. X            }
  1742. X            if(p->valid == EMPTY)
  1743. X                p = p->next;
  1744. X        } while(p != (folder) NULL && p->valid != true);
  1745. X        if(p == (folder) NULL)
  1746. X            addstatus("can't go forward that many folders", true);
  1747. X        else {
  1748. X            alternate = curflr;
  1749. X            curflr = p;
  1750. X            curmail = p->mail;
  1751. X            y = FIRST;
  1752. X            display_page();
  1753. X        }
  1754. X    }
  1755. X}
  1756. X
  1757. X
  1758. X/* --------------------
  1759. X    Goto previous folder, make active if not so already.
  1760. X-------------------- */
  1761. Xvoid
  1762. Xgoto_prev_folder(count)
  1763. X    int        count;
  1764. X{
  1765. X    bool    changed = false;
  1766. X    folder    f, p = curflr;
  1767. X
  1768. X    for( ; count > 0 ; count--) {
  1769. X            /* skip other pages of current folder */
  1770. X        for(f=p ; p->prev != (folder) NULL && p->prev->name == f->name ;
  1771. X            p=p->prev)
  1772. X            ;
  1773. X        if(curflr->prev == (folder) NULL || p->prev == (folder) NULL) {
  1774. X            addstatus("first folder", true);
  1775. X            break;
  1776. X        } else {
  1777. X            changed = true;
  1778. X            p = p->prev;
  1779. X        }
  1780. X    }
  1781. X    if(changed) {
  1782. X        do {
  1783. X            if(!p->valid) {
  1784. X                p->valid = true;
  1785. X                addstatus("reading mail headers ...", true);
  1786. X                (void)find_mail(p, false);
  1787. X            }
  1788. X            if(p->valid == EMPTY)
  1789. X                p = p->prev;
  1790. X        } while(p != (folder) NULL && p->valid != true);
  1791. X        if(p == (folder) NULL)
  1792. X            addstatus("can't go back that many folders", true);
  1793. X        else {
  1794. X                /* skip other pages of current folder */
  1795. X            for(f=p ; p->prev != (folder) NULL &&
  1796. X                p->prev->name == f->name ; p=p->prev)
  1797. X                ;
  1798. X            alternate = curflr;
  1799. X            curflr = p;
  1800. X            curmail = p->mail;
  1801. X            y = FIRST;
  1802. X            display_page();
  1803. X        }
  1804. X    }
  1805. X}
  1806. X
  1807. X
  1808. X/* --------------------
  1809. X    Make new folder current as specified - read from terminal (get_name =
  1810. X    true) or use value in alternate (get_name = false).
  1811. X-------------------- */
  1812. Xvoid
  1813. Xgoto_folder(get_name)
  1814. X    bool    get_name;
  1815. X{
  1816. X    char    buf[LEN], *str = buf;
  1817. X    folder    f;
  1818. X    int        i;
  1819. X
  1820. X    if(get_name || alternate == (folder) NULL) {
  1821. X            /* no alternate folder */
  1822. X        get_string("folder? ", str);
  1823. X        for(i=0 ; *str == ' ' ; i++, str++)
  1824. X            ;
  1825. X        for(; i < LEN && buf[i] != ' ' && buf[i] != '\0' ; i++)
  1826. X            ;
  1827. X        if(i < LEN)
  1828. X            buf[i] = '\0';
  1829. X        GOTO_NAME(f, str);
  1830. X        if(f == (folder) NULL) {
  1831. X            addstatus("no such folder", true);
  1832. X            return;
  1833. X        }
  1834. X        if(!f->valid) {
  1835. X            f->valid = true;
  1836. X            addstatus("reading mail headers ...", true);
  1837. X            (void)find_mail(f, false);
  1838. X            if(f->valid == EMPTY) {
  1839. X                (void)sprintf(str, "%s -- folder empty", f->name);
  1840. X                addstatus(str, true);
  1841. X                return;
  1842. X            }
  1843. X        }
  1844. X    } else
  1845. X        f = alternate;
  1846. X    if(f == curflr)
  1847. X        addstatus("already in that folder", true);
  1848. X    else {
  1849. X        alternate = curflr;
  1850. X        curflr = f;
  1851. X        curmail = f->mail;
  1852. X        y = FIRST;
  1853. X        display_page();
  1854. X    }
  1855. X}
  1856. X
  1857. X
  1858. X/* --------------------
  1859. X    Go to first line of page, as offset by count.
  1860. X-------------------- */
  1861. Xvoid
  1862. Xcursor_first(count)
  1863. X    int        count;
  1864. X{
  1865. X    item    m = curflr->mail;
  1866. X
  1867. X    addstatus("", false);                /* clear status line */
  1868. X    for(y=FIRST ; m != (item) NULL && count > 1 ; count--, y++, m=m->next)
  1869. X        ;
  1870. X    if(m == (item) NULL)
  1871. X        beep();
  1872. X    else {
  1873. X        curmail = m;
  1874. X        move(y, 0);
  1875. X        refresh();
  1876. X    }
  1877. X}
  1878. X
  1879. X
  1880. X/* --------------------
  1881. X    Go to middle line of page.
  1882. X-------------------- */
  1883. Xvoid
  1884. Xcursor_middle()
  1885. X{
  1886. X    item    m, p;
  1887. X    bool    tog = false;
  1888. X
  1889. X    addstatus("", false);                /* clear status line */
  1890. X        /* find middle of page - p traverses page at half speed */
  1891. X    for(y=FIRST, m=p=curflr->mail ; m != (item) NULL ; m=m->next, tog= !tog)
  1892. X        if(tog) {
  1893. X            y++;
  1894. X            p = p->next;
  1895. X        }
  1896. X    curmail = p;
  1897. X    move(y, 0);
  1898. X    refresh();
  1899. X}
  1900. X
  1901. X
  1902. X/* --------------------
  1903. X    Go to last line of page, as offset by count.
  1904. X-------------------- */
  1905. Xvoid
  1906. Xcursor_last(count)
  1907. X    int        count;
  1908. X{
  1909. X    item    m = curflr->mail;
  1910. X
  1911. X    addstatus("", false);                /* clear status line */
  1912. X        /* find last item, including y-value */
  1913. X    for(y=FIRST ; m->next != (item) NULL ; y++, m=m->next)
  1914. X        ;
  1915. X    for(; m != (item) NULL && count > 1 ; count--, y--, m=m->prev)
  1916. X        ;
  1917. X    if(m == (item) NULL)
  1918. X        beep();
  1919. X    else {
  1920. X        curmail = m;
  1921. X        move(y, 0);
  1922. X        refresh();
  1923. X    }
  1924. X}
  1925. X
  1926. X
  1927. X/* --------------------
  1928. X    Go to first page.  ***should use count as offset*** 
  1929. X-------------------- */
  1930. Xvoid
  1931. Xgoto_first_page()
  1932. X{
  1933. X    folder    f;
  1934. X
  1935. X    f = folders; NEXT_VALID(f);
  1936. X    if(f == (folder) NULL) {
  1937. X        /* no valid folders - bleah?! */
  1938. X        addstatus("no valid folders, exiting", true);
  1939. X        to_normal();
  1940. X        exit(1);
  1941. X    } else if(f != curflr) {
  1942. X        alternate = curflr;
  1943. X        curflr = f;
  1944. X        curmail = f->mail;
  1945. X        y = FIRST;
  1946. X        display_page();
  1947. X    }
  1948. X}
  1949. X
  1950. X
  1951. X/* --------------------
  1952. X    Go to last page.  ***should use count as offset***
  1953. X-------------------- */
  1954. Xvoid
  1955. Xgoto_last_page()
  1956. X{
  1957. X    folder    f, p;
  1958. X
  1959. X    for(f=folders ; f != (folder) NULL ; f=f->next)
  1960. X        if(f->valid)
  1961. X            p = f;
  1962. X    if(p == (folder) NULL) {
  1963. X        /* no valid folders - bleah?! */
  1964. X        addstatus("no valid folders, exiting", true);
  1965. X        to_normal();
  1966. X        exit(1);
  1967. X    } else if(p != curflr) {
  1968. X        alternate = curflr;
  1969. X        curflr = p;
  1970. X        curmail = p->mail;
  1971. X        y = FIRST;
  1972. X        display_page();
  1973. X    }
  1974. X}
  1975. END_OF_page.c
  1976. if test 8170 -ne `wc -c <page.c`; then
  1977.     echo shar: \"page.c\" unpacked with wrong size!
  1978. fi
  1979. # end of overwriting check
  1980. fi
  1981. if test -f refresh.c -a "${1}" != "-c" ; then 
  1982.   echo shar: Will not over-write existing file \"refresh.c\"
  1983. else
  1984. echo shar: Extracting \"refresh.c\" \(1896 characters\)
  1985. sed "s/^X//" >refresh.c <<'END_OF_refresh.c'
  1986. X#ifndef lint
  1987. Xstatic char *RCS_refresh_folder_c = "$Id: refresh.c,v 1.1 90/09/19 14:00:09 rogers Exp $";
  1988. X#endif
  1989. X
  1990. X/* --------------------
  1991. X    vmail -- refresh_folder.c
  1992. X
  1993. X    Routine for rescanning a folder.
  1994. X
  1995. X    James Perkins 9-19-90 (jamesp@metolius.wr.tek.com)
  1996. X-------------------- */
  1997. X
  1998. X#include "defs.h"
  1999. X
  2000. X/* --------------------
  2001. X    Refresh the folder's display - reread the scan listing
  2002. X-------------------- */
  2003. Xvoid
  2004. Xrefresh_folder()
  2005. X{
  2006. X    folder    f, p;
  2007. X    char    *curfname = curflr->name;
  2008. X    char    str[LEN];
  2009. X
  2010. X    /*
  2011. X     * INACTIVATE CURRENT FOLDER
  2012. X     */
  2013. X
  2014. X    /* find first, last page of folder */
  2015. X    p = curflr; FRST_OF_NAME(p);
  2016. X    f = curflr; LAST_OF_NAME(f);
  2017. X
  2018. X    /* free (should really, actually free here...) */
  2019. X    p->next = f->next;
  2020. X    p->valid = false;
  2021. X    p->mail = p->last = (item) NULL;
  2022. X    p->pagenum = p->pages = 1;
  2023. X    if(p->next != (folder) NULL)
  2024. X        p->next->prev = p;
  2025. X
  2026. X    /* Get new current folder in case the re-scan comes up empty */
  2027. X    curflr = p;
  2028. X    NEXT_VALID(curflr);
  2029. X    if(curflr == (folder) NULL) {
  2030. X        curflr = p;
  2031. X        PREV_VALID(curflr);
  2032. X    }
  2033. X    if(curflr == (folder) NULL) {
  2034. X        /* Note: just made the last folder inactive ... */
  2035. X    }
  2036. X
  2037. X    /*
  2038. X     * GOTO ORIGINAL, STARTING FOLDER NAME
  2039. X     */
  2040. X
  2041. X    GOTO_NAME(f, curfname);
  2042. X    if(f == (folder) NULL) {
  2043. X        addstatus("no such folder", true);
  2044. X        return;
  2045. X    }
  2046. X    if(!f->valid) {
  2047. X        f->valid = true;
  2048. X        addstatus("re-reading mail headers ...", true);
  2049. X        (void)find_mail(f, false);
  2050. X        if(f->valid == EMPTY) {
  2051. X            /* go to another valid folder (found by code above) */
  2052. X            if (curflr == (folder) NULL) {
  2053. X                /* No other valid folder to go to! */
  2054. X                addstatus("Last active folder is empty", true);
  2055. X                to_normal();
  2056. X                exit(0);
  2057. X            }
  2058. X            (void)sprintf(str, "%s -- folder empty", f->name);
  2059. X            addstatus(str, true);
  2060. X            f = curflr;
  2061. X        }
  2062. X    }
  2063. X    else {
  2064. X        addstatus("internal error: folder unexpectedly valid!", true);
  2065. X        to_normal();
  2066. X        exit(0);
  2067. X    }
  2068. X
  2069. X    alternate = (folder) NULL;
  2070. X    curflr = f;
  2071. X    curmail = f->mail;
  2072. X    y = FIRST;
  2073. X    display_page();
  2074. X}
  2075. END_OF_refresh.c
  2076. if test 1896 -ne `wc -c <refresh.c`; then
  2077.     echo shar: \"refresh.c\" unpacked with wrong size!
  2078. fi
  2079. # end of overwriting check
  2080. fi
  2081. echo shar: End of archive 1 \(of 3\).
  2082. cp /dev/null ark1isdone
  2083. MISSING=""
  2084. for I in 1 2 3 ; do
  2085.     if test ! -f ark${I}isdone ; then
  2086.     MISSING="${MISSING} ${I}"
  2087.     fi
  2088. done
  2089. if test "${MISSING}" = "" ; then
  2090.     echo You have unpacked all 3 archives.
  2091.     rm -f ark[1-9]isdone
  2092. else
  2093.     echo You still need to unpack the following archives:
  2094.     echo "        " ${MISSING}
  2095. fi
  2096. ##  End of shell archive.
  2097. exit 0
  2098.